package com.liry.zk;

import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;

/**
 * 分布式锁 - 非公平锁测试
 *
 * @author ALI
 * @since 2022/12/25
 */
public class TestTheadLock {
    static int count = 0;

    public static void main(String[] args) throws InterruptedException {
        //        nonFairLock();
        fairLock();
    }

    private static void nonFairLock() throws InterruptedException {
        NonfairSyncLock lock = new NonfairSyncLock();

        CountDownLatch latch = new CountDownLatch(1000);
        List<Thread> threadList = IntStream.range(0, 1000).mapToObj(d -> new Thread(() -> {
            lock.lock();
            count += 1;
            latch.countDown();
            lock.unlock();
        }, "线程-" + d)).collect(Collectors.toList());

        threadList.forEach(Thread::start);

        latch.await();
        System.out.println("最终结果应是1000：" + count);
    }

    private static void fairLock() throws InterruptedException {
        // 使用curator客户端
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        CuratorFramework client = CuratorFrameworkFactory.builder()
                                                         .connectString("192.168.17.128:2181")
                                                         .sessionTimeoutMs(3000)
                                                         .connectionTimeoutMs(3000)
                                                         .retryPolicy(retryPolicy)
                                                         .build();
        client.start();

        InterProcessMutex lock = new InterProcessMutex(client, "/lock");

        CountDownLatch latch = new CountDownLatch(1000);
        List<Thread> threadList = IntStream.range(0, 1000).mapToObj(d -> new Thread(() -> {
            try {
                lock.acquire();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            count += 1;
            latch.countDown();
            try {
                lock.release();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }, "线程-" + d)).collect(Collectors.toList());

        threadList.forEach(Thread::start);

        latch.await();
        System.out.println("最终结果应是1000：" + count);
    }
}
